package com.example.spring_boot_integration.config;

import com.rometools.rome.feed.synd.SyndEntry;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.MessageChannels;
import org.springframework.integration.dsl.Pollers;
import org.springframework.integration.feed.inbound.FeedEntryMessageSource;
import org.springframework.integration.file.dsl.Files;
import org.springframework.integration.file.support.FileExistsMode;
import org.springframework.integration.mail.dsl.Mail;
import org.springframework.integration.scheduling.PollerMetadata;

import java.io.File;
import java.io.IOException;

import static java.lang.System.getProperty;

/**
 * @author ljw
 * @description
 * @date 2022/9/15 10:30
 */
@Configuration
public class IntegrationConfig {

    //获取 http://spring.io/blog.atom 的资源
    @Value("http://spring.io/blog.atom")
    private Resource resource;

    /**
     * 使用 Fluent API 和 Pollers 配置默认的轮询方式
     * @author ljw
     * @date 2022/9/15 11:07
     */
    @Bean(name=PollerMetadata.DEFAULT_POLLER)
    public PollerMetadata poller() {
        return Pollers.fixedRate(500).get();
    }

    /**
     * 构造 feed 的入站通道适配器作为数据输入
     * @author ljw
     * @date 2022/9/15 11:33
     */
    @Bean
    public FeedEntryMessageSource feedMessageSource() throws IOException {
        FeedEntryMessageSource messageSource = new FeedEntryMessageSource(resource.getURL(), "news");
        return messageSource;
    }

    /**
     * 读取数据
     * @author ljw
     * @date 2022/9/15 12:27
     */
    @Bean
    public IntegrationFlow myFlow() throws IOException {
        return IntegrationFlows.from(feedMessageSource()) //流程从 from 方法开始
                //通过路由方法 route 来选择路由，消息体（payload） 的类型为 SyndEntry,作为判断条件的类型为 String,
                // 判断的值是通过 payload 获得的分类（Category）
                .<SyndEntry, String>route(payload -> payload.getCategories().get(0).getName(),
                //通过不同分类的值转向不同的消息通道，分类为 releases 转向 releasesChannel，分类为 engineering 转向 engineeringChannel，分类为 news 转向 newsChannel，
                mapping -> mapping.channelMapping("releases", "releasesChannel") //
                        .channelMapping("engineering", "engineeringChannel")
                        .channelMapping("news", "newsChannel"))
                .get(); //通过 get 方法获得 IntegrationFlow 实体， 配置为 Spring 的 Bean
    }

    /**
     * 输出数据
     * @param
     * @author ljw
     * @date 2022/9/16 10:37
     */
    @Bean
    public IntegrationFlow releasesFlow() {
        //从消息通道 releasesChannel 开始获取数据
        return IntegrationFlows.from(MessageChannels.queue("releasesChannel", 10))
                //使用 transform 方法进行数据转换。payload 类型为 SyndEntry，将其转换为字符串类型
                .<SyndEntry, String> transform(payload -> " 《"+payload.getTitle()+"》 "+payload.getLink()+getProperty("line.separator"))
                //用 handle 方法处理 file 的出站适配器。 Files 类是由 Spring Integration Java DSL 提供的 Fluent API 用来构造文件输出的适配器
                .handle(Files.outboundAdapter(new File("G:\\springblog"))
                                .fileExistsMode(FileExistsMode.APPEND)
                                .charset("UTF-8")
                                .fileNameGenerator(message -> "releases.txt")
                                .get()
                )
                .get();

    }

    /**
     * 输出数据
     * @param
     * @author ljw
     * @date 2022/9/16 11:23
     */
    @Bean
    public IntegrationFlow engineeringFlow() {
        return IntegrationFlows.from(MessageChannels.queue("engineeringChannel", 10))
                .<SyndEntry, String> transform(e -> "《"+e.getTitle()+"》"+e.getLink()+getProperty("line.separator"))
                .handle(Files.outboundAdapter(new File("G:\\springblog"))
                        .fileExistsMode(FileExistsMode.APPEND)
                        .charset("UTF-8")
                        .fileNameGenerator(message -> "engineering.txt")
                        .get()
                )
                .get();
    }

    @Bean
    public IntegrationFlow newsFlow() {
        return IntegrationFlows.from(MessageChannels.queue("newsChannel", 10))
                .<SyndEntry, String>transform(payload -> " 《"+payload.getTitle()+"》 "+payload.getLink()+getProperty("line.separator"))
                //通过 enrichHeaders 来增加消息头信息
                .enrichHeaders(Mail.headers().subject("来自 Spring 的新闻").to("18328469867@163.com").from("18328469867@163.com"))
                //邮件发送的相关信息通过 Spring Integration Java DSL 提供的 Mail 的 headers 方法来构造， handle 方法定义邮件发送的出站适配器
                .handle(Mail.outboundAdapter("smtp.163.com").port(25).protocol("smtp").credentials("18328469867@163.com", "*****").javaMailProperties(p -> p.put("mail.debug", "flase")),
                        e -> e.id("smtpOut"))
                .get();
    }
}
